define('framework/associate/GillionAssociateDirectiveConstructor', ['angular'], function (angular) {

    return function ($compile, $dataSourceManager, $parse, $timeout, $filter,$document,$tabindex,GillionLocationService,GillionMsgService) {
        var CREATEDOBJ = "isCreatedObj";
        var extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
            hasProp = {}.hasOwnProperty;
        var AssociateMulti;

        var associateTmpl = //'<input type="text" class="form-text form-suggestbox" value=""  />' +
            '<div ng-show="tableShow" class="form-suggestbox-dropdown" style="display: inline-block">' +
            '<div  class="form-suggestbox-pager" ng-show="pageShow">'+
            '<span>找到 {{totalRecord}} 条记录，显示{{recordFrom}}到{{recordTo}}</span>'+
            '<button type="button" class="btn"  ng-click="associate.goPrePage()"><i class="fi fi-reverse"></i></button>'+
            '<button type="button" class="btn" ng-click="associate.goNextPage()"><i class="fi fi-forward"></i></button>'+
            '</div>' +
            '<table class="form-suggestbox-table">'+
            '<tr class="transclude-tr"></tr>'+
            '<tr ng-click="rowClick(record,$event,$index)" ng-repeat="record in dataSource" g-repeat-finish>' +
            '<td ng-if="multi" ><div class="form-clickbox" selected="selected" ng-if="selected[$index]"><i class="fi" ></i></div>' +
            '<div class="form-clickbox"  ng-if="!selected[$index]"><i class="fi" ></i></div></td>' +
            '<td ng-repeat="th in columns">{{record[th]}}</td></tr>'+
            '</table></div>';
        //判断是否空对象或空数组
        function isEmptyObject( obj ) {
            if(obj==undefined) return true;
            if(angular.isArray(obj)){
                return obj.length == 0;
            }else{
                for ( var name in obj ) {
                    return false;
                }
                return true;
            }
        }

        function clearObject(obj){
            if(obj==undefined) return ;
            if(angular.isArray(obj)){
                obj.length = 0;
                return;
            }else{
                for ( var name in obj ) {
                    obj[name] = undefined;
                }
            }
        }

        function Associate($scope, $element, $attrs,ngModel) {
            var me = this;
            me.element = $element;
            me.attrs = $attrs;
            me.scope = $scope;
            me.ngModel = ngModel;
        }

        Associate.prototype.doFilters = function (record, columns, filterNames) {
            var i, len, col, filterToken,tokens;
            for (i = 0, len = columns.length; i < len; i++) {
                col = columns[i];
                filterToken = filterNames[i];
                if(col && filterToken && record[col]){
                    if(filterToken.indexOf('|') == -1){
                        if(!record[col+"_$bak"]){
                            record[col+"_$bak"] = record[col];
                        }
                        record[col] = $filter(filterToken)(record[col]);
                    }else{
                        tokens = filterToken.split('|');
                        angular.forEach(tokens,function(item){
                            if(item.indexOf(":") != -1){
                                item = item.split(":");
                                if(!record[col+"_$bak"]){
                                    record[col+"_$bak"] = record[col];
                                }
                                record[col] = $filter(item[0])(record[col],item[1]);
                            }else{
                                if(!record[col+"_$bak"]){
                                    record[col+"_$bak"] = record[col];
                                }
                                record[col] = $filter(item)(record[col]);
                            }
                        });
                    }
                }
            }

        };
        /**
         * 跳页
         */
        Associate.prototype.goPage = function (page, callback) {
            var me = this,
                scope = me.scope;
            scope.isOperSelf = true;
            if(me.attrs.keyword){
                scope.keywordSetter(scope.$parent,scope.blurText);
            }
            $dataSourceManager.dataSources[scope.sourceName].currentPage=page;
            $dataSourceManager.dataSources[scope.sourceName].doRequestData();
            //this.initDataSource(callback);
        };

        Associate.prototype.goPrePage = function(){
            var me = this,
                scope = me.scope,
                attrs = me.attrs;
            if(scope.page != 1){
                me.goPage(scope.page -1);
            }
        }

        Associate.prototype.goNextPage = function(){
            var me = this,
                scope = me.scope,
                attrs = me.attrs;
            if(scope.page != scope.totalPage && scope.totalPage > 1){
                me.goPage(scope.page +1)
            }
        }

        Associate.prototype.apply = function () {
            var scope = this.scope;
            if(!scope.$root.$$phase){
                scope.$apply();
            }
        };

        /**
         * rowData去重
         */
        Associate.prototype.dupRemoval= function(rowDatas){

            var result = [], hash = {},value;
            for (var i = 0, elem; (elem = rowDatas[i]) != null; i++) {
                value = this.scope.valuePropGetter(elem);
                if (!hash[value]) {
                    result.push(elem);
                    hash[value] = true;
                }
            }
            return result;
        };

        Associate.prototype.displayInit = function(display,value){

            var myScope = this.scope,
                selectedRow = {};

            if(myScope.$selectedRow && !isEmptyObject(myScope.$selectedRow) ){
                selectedRow = myScope.$selectedRow;
            }else{
                if(this.attrs.selectedRow){
                    myScope.$parent[this.attrs.selectedRow] = selectedRow;
                }
            }
            selectedRow[myScope.displayExpress] = display;
            selectedRow[myScope.valueProp] = value;
            myScope.$selectedRow = selectedRow;
            myScope.selectedRow = selectedRow;

            this.selectedRowToDisplay();
            this.keywordSelected();
            this.selectedRowToModelValue();
        };

        /**
         * 选择第一个
         */
        Associate.prototype.choseFirst = function(){
            var me = this,
                scope = me.scope;
            if(scope.dataSource && scope.dataSource.length==1){
                var rowData = scope.dataSource[0];
                if(scope.inputText.val().toLowerCase()===me.getDisplay(rowData).toLowerCase()){
                    me.rowClick(scope.dataSource[0]);
                    return true;
                }else{
                    if(scope.unmatchRemove && scope.isOperSelf){
                        scope.$selectedRow = {};
                        scope.setModelValue('');
                    }
                }
            }
            return false;
        };

        /**
         * 每次请求数据初始化
         * @param callback
         */
        Associate.prototype.initDataSource= function(callback){
            var me = this, i,
                scope = me.scope,
                attrs = me.attrs,
                clear = false,
                dataFunc = function(context,dataSource){
                    if(angular.element(me.element).parents("body").size() == 0){
                        //此处是防止dom被remove掉的时候 还会执行回调（表格中）
                        scope.$$listeners = {};
                        return;
                    }
                    scope.totalRecord = dataSource.totalRecord;
                    if(!scope.totalRecord ){
                        scope.recordFrom = 0;
                        scope.recordTo = 0;
                    }else{
                        scope.recordFrom = (dataSource.currentPage-1)*dataSource.pageSize+1;
                        if(dataSource.records){
                            scope.recordTo = scope.recordFrom+dataSource.records.length-1;
                        }else{
                            scope.recordTo = scope.recordFrom;
                        }
                    }
                    scope.dataSource =  dataSource.records;
                    if(scope.dataSource){
                        angular.forEach(scope.dataSource,function(item){
                            me.doFilters(item,scope.columns,scope.filters);
                        });
                    }
                    if(document.activeElement == scope.inputText[0]){
                        scope.isOperSelf = true;
                    }
                    scope.page = dataSource.currentPage;
                    scope.totalPage = dataSource.totalPage;
                    scope.pageShow = scope.totalRecord > 10 && attrs.pageShow!="false";
                    if(me.attrs.multi){
                        if(scope.unmatchRemove){
                            me.showSelected();
                        }else{
                            me.unmatchKeep();
                        }
                    }else{
                        if(scope.unmatchRemove ){
                            if(!scope.dataSource || scope.dataSource.length==0){
                                clear = true;
                            }else{
                                clear = true;
                                angular.forEach(scope.dataSource,function(item){
                                    if(scope.inputText.val().toLowerCase()===me.getDisplay(item).toLowerCase()){
                                        clear = false;
                                    }
                                })
                            }
                            if(clear){
                                if(scope.$selectedRow){
                                    scope.$selectedRow[scope.displayExpress] = undefined;
                                    scope.$selectedRow[scope.valueProp] = undefined;
                                    scope.$selectedRow = angular.extend({},scope.$selectedRow);
                                }
                                //clearObject(scope.$selectedRow);
                                //scope.setModelValue('');
                            }
                        }
                    }
                    if (attrs.requestStatus){
                        scope.requestStatusSetter(scope.$parent,false);
                    }
                    if( document.activeElement == scope.inputText[0]){
                        me.showView();
                        scope.$tableWrapper.css("display","block");
                    }
                    scope.currIndex = -1;
                    me.apply();
                    if (angular.isFunction(callback)) {
                        callback.call(me);
                    }
                };
            //判断数据源是否有数据
            if($dataSourceManager.dataSources[scope.sourceName] && $dataSourceManager.dataSources[scope.sourceName].records){
                dataFunc(null,$dataSourceManager.dataSources[scope.sourceName]);
            }
            scope.$on(scope.sourceName,dataFunc);
        };
        /**
         * 重新搜索
         */
        Associate.prototype.reSearch = function (delayTime) {
            var me = this,
                scope = me.scope,
                attrs = me.attrs,
                params,
                myDataSource;
            delayTime = delayTime || 0;
            if (me.reSearchTimer) {
                $timeout.cancel(me.reSearchTimer);
                me.reSearchTimer = undefined;
            }
            myDataSource = $dataSourceManager.dataSources[scope.sourceName];
            //if (!angular.isUndefined(myDataSource) && !angular.isUndefined(myDataSource.reqTimer)){
            //    $dataSourceManager.dataSources[scope.sourceName].$timeout.cancel(myDataSource.reqTimer);
            //}
            if (attrs.requestStatus){
                scope.requestStatusSetter(scope.$parent,true);
            }

            me.reSearchTimer = $timeout(function () {
                    //请求关键词
                    if(me.attrs.multi){
                        scope.$keyword = me.showSelected().join(scope.valueSeparator);
                    }else{
                        scope.$keyword = scope.inputText.val();
                    }
                    //字符串是否搜索最短长度
                    var charLength = scope.$keyword ? scope.$keyword.length:0;
                    if((scope.$keyword==scope.valueSeparator && scope.charLengthSearch>0)
                        || scope.charLengthSearch>charLength){
                        return;
                    }

                    if(angular.isFunction($dataSourceManager.dataSources[scope.sourceName].params)){
                        if(!me.oldParamFun){
                            me.oldParamFun = $dataSourceManager.dataSources[scope.sourceName].params;
                        }

                        //对参数的函数封装
                        function paramsFun(){
                            var paramNew = me.oldParamFun.call();
                            scope.keywordPropertySetter(paramNew, scope.$keyword);
                            return paramNew;
                        }
                        if($dataSourceManager.dataSources[scope.sourceName].params.toString().indexOf("paramsFun()")==-1 ){
                            params = paramsFun;
                        }else{
                            params = $dataSourceManager.dataSources[scope.sourceName].params;
                        }

                    }else{
                        params = angular.extend({}, $dataSourceManager.dataSources[scope.sourceName].params  || {});
                        scope.keywordPropertySetter(params, scope.$keyword);
                    }

                    //更新keyword参数 会重新刷新请求
                    $dataSourceManager.dataSources[scope.sourceName].currentPage = 1;
                    $dataSourceManager.dataSources[scope.sourceName].params=params;
                    $dataSourceManager.dataSources[scope.sourceName].doRequestData();
                    me.reSearchTimer = undefined;
                    if(scope.dataSource
                        && scope.dataSource.length>0
                        && document.activeElement == scope.inputText[0]){
                        me.showView();
                    }
            }, delayTime);

        };

        Associate.prototype.rowClick = function (rowData,$event) {
            //取消blur事件
            if(this.scope.timer){
                $timeout.cancel(this.scope.timer);
            }

            var self =this;
            if (angular.isDefined(self.attrs.onBeforeSelect)) {
                if (self.scope.onBeforeSelect({
                        list: self,
                        $event:$event,
                        item: rowData
                    }) === false) {
                    return;
                }
            }

            var me = this,
                scope = me.scope,
            element=me.element;
            scope.setModelValue(scope.valuePropGetter(rowData));
            scope.inputText.val(me.getDisplay(rowData));
            scope.$selectedRow = angular.extend({},rowData);

            if (angular.isDefined(self.attrs.onSelect)) {
                self.scope.onSelect({
                    list: self,
                    $event:$event,
                    item: rowData
                });
            }
            scope.isOperSelf = true;
            me.hideView();
        };

        Associate.prototype.getDisplay = function (rowData) {
            var value = $parse(this.scope.displayExpress)(rowData);
            value =!!value?value.toString().replace(/<[^>]+>/g, ""):'';
            return value || '';
        };

        Associate.prototype.hideView = function () {
            this.scope.tableShow = false;
        };

        Associate.prototype.showView = function () {
            var scope = this.scope;
            var location = GillionLocationService.calculateLocation(this.element);
            //移除angular的隐藏属性 为了计算得到宽度
            scope.$tableWrapper.removeClass("ng-hide");
            var tableWidth = scope.$tableWrapper[0].offsetWidth,
                tableHeight = scope.$tableWrapper[0].offsetHeight;
            if(scope.$tableWrapper.css("display") == "none"){
                scope.$tableWrapper.css("display","block");
                tableWidth = scope.$tableWrapper[0].offsetWidth;
                tableHeight = scope.$tableWrapper[0].offsetHeight;
                scope.$tableWrapper.css("display","none");
            }
            var pagerWidth = scope.$tableWrapper.find(".form-suggestbox-pager").width();
            if(tableWidth < pagerWidth){
                scope.$tableWrapper.find("table").css("min-width",pagerWidth);
            }
            if(location.right < tableWidth){
                location.left = location.left - (tableWidth - location.right);
            }
            scope.$tableWrapper.css("left",location.left);//scope.inputText.position().left);
            if(location.bottom - 10 > tableHeight || !scope.dataSource || scope.dataSource.length == 0){
                scope.$tableWrapper.css("top",location.top+scope.inputText[0].offsetHeight);//scope.inputText.position().top+scope.inputText[0].offsetHeight);
            }else{
                scope.$tableWrapper.css("top",location.top - tableHeight);
            }

            scope.tableShow = true;
        };

        Associate.prototype.showSelected = function(){
            var me = this,
                scope = me.scope;
            if(scope.dataSource && scope.dataSource.length==1){
                var rowData = scope.dataSource[0];
                if(scope.inputText.val().toLowerCase()===me.getDisplay(rowData).toLowerCase()){
                    me.rowClick(scope.dataSource[0]);
                }else{
                    scope.$selectedRow = {};
                    scope.setModelValue('');
                }
            }
        };
        /**
         * 未匹配的保留处理
         */
        Associate.prototype.unmatchKeep = function(){
            var self = this,
                scope = this.scope,
            selectedRow = {},
                rowData = {},
                index,length = 0;

            rowData[scope.displayExpress] = scope.inputText.val();
            rowData[scope.valueProp] = scope.inputText.val();
            if (angular.isDefined(self.attrs.onBeforeSelect)) {
                if (self.scope.onBeforeSelect({
                        list: this,
                        $event:null,
                        item: rowData
                    }) === false) {
                    return;
                }
            }

            if(scope.$selectedRow &&
                scope.$selectedRow[scope.displayExpress] == scope.$selectedRow[scope.valueProp] ){
                if(scope.dataSource){
                    length = scope.dataSource.length ;
                }
                //存在于选择列表 则无需构造
                for(index = 0; index < length; index++){
                    if(scope.dataSource[index][scope.valueProp]
                        == scope.$selectedRow[scope.valueProp]){
                        return;
                    }
                }
                selectedRow = angular.extend({},scope.$selectedRow);
                selectedRow[scope.displayExpress] = scope.inputText.val();
                selectedRow[CREATEDOBJ] = true;

                selectedRow[scope.valueProp] = scope.inputText.val();
                scope.setModelValue(scope.inputText.val());
                scope.$selectedRow = selectedRow;
            }
            if (angular.isDefined(self.attrs.onSelect)) {
                self.scope.onSelect({
                    list: self,
                    $event:null,
                    item: rowData
                });
            }
        };

        Associate.prototype.selectedRowToDisplay = function(){
            var me = this,
                scope = me.scope;
            scope.inputText.val(me.getDisplay(scope.$selectedRow));
            if(me.attrs.keyword){
                scope.keyword = scope.inputText.val();
            }
        };

        Associate.prototype.selectedRowToModelValue = function(){
            var me = this,
                scope = me.scope;

            scope.setModelValue(scope.valuePropGetter(scope.$selectedRow));
        };

        Associate.prototype.keywordSelected = function(){

        };

        AssociateMulti = (function (superClass) {
            extend(AssociateMulti, superClass);
            function AssociateMulti($scope, $element, $attrs,ngModel){
                this.scope = $scope;
                this.attrs = $attrs;
                this.element = $element;
                this.ngModel = ngModel;
                AssociateMulti.__super__.constructor.call(this, this.scope,this.element,this.attrs,this.ngModel);
            }

            AssociateMulti.prototype.rowClick = function (rowData,$event,index) {
                var self =this;
                if(self.scope.timer){
                    $timeout.cancel(self.scope.timer);
                }

                if (angular.isDefined(self.attrs.onBeforeSelect)) {
                    if (self.scope.onBeforeSelect({
                            list: self,
                            $event:$event,
                            item: rowData
                        }) === false) {
                        return;
                    }
                }

                var displayArray = [],
                    submitArray = [],
                    me = this,
                    selectLength, i,
                    myScope = me.scope,
                length = myScope.dataSource.length;
                myScope.selected[index]=!myScope.selected[index];
                var checkbox = myScope.$tableWrapper.find("div.form-clickbox:eq("+index+")");
                myScope.isOperSelf = true;
                //已选中的处理
                if(myScope.selected[index]){
                    checkbox.attr("selected","selected");
                    myScope.$selectedRow.push(rowData);
                }else{
                    checkbox.removeAttr("selected");
                    selectLength = myScope.$selectedRow.length;
                    for(i=0; i < selectLength; i++){
                        var each = myScope.$selectedRow[i];
                        if(myScope.valuePropGetter(rowData)===myScope.valuePropGetter(each)){
                            myScope.$selectedRow.splice(i,1);
                            break;
                        }
                    }
                }
                selectLength = myScope.$selectedRow.length;
                for(i = 0; i<selectLength; i++){
                    var each = myScope.$selectedRow[i];
                    if(myScope.valuePropGetter(each)){
                        submitArray.push(myScope.valuePropGetter(each));
                    }
                    if(me.getDisplay(each)){
                        displayArray.push(me.getDisplay(each));
                    }
                }
                myScope.setModelValue(submitArray.join(myScope.valueSeparator));
                myScope.inputText.val(displayArray.join(myScope.valueSeparator));

                if (angular.isDefined(self.attrs.onSelect)) {
                    self.scope.onSelect({
                        list: self,
                        $event:$event,
                        item: rowData
                    });
                }
            };

            /**根据输入框显示勾选和更改selectedRow 并返回未匹配的key数组*/
            AssociateMulti.prototype.showSelected = function(){
                var me = this;
                var selectedArr = me.keywordSelected();
                var missKeyArr = me.keywordSelectedRow(selectedArr);
                me.selectedRowToModelValue();
                if(missKeyArr.length>0 && me.scope.unmatchRemove){
                    //如果仍有未选中的 则只显示出最后一个未选中的
                    me.selectedRowToDisplay(missKeyArr[missKeyArr.length-1]);
                }
                return missKeyArr;
            };
            //根据输入框内容 更改显示checkbox 并返回已选的行数组
            AssociateMulti.prototype.keywordSelected = function(){
                var me = this,
                    scope = me.scope,
                    index = 0,
                    inputVal = scope.inputText.val(),
                    selectedArr=[];
                if(inputVal) {
                    var keywordArr = inputVal.split(scope.valueSeparator);
                    if(!scope.deleteOperate && scope.$selectedRow.length != keywordArr.length){
                        //非删除的时候 最后一个不勾选
                        keywordArr = keywordArr.splice(0,keywordArr.length-1);
                    }
                    //勾选checkbox
                    if(scope.dataSource){
                        angular.forEach(scope.dataSource,function (each) {
                            if (_(keywordArr).filter(function (item) {
                                    return me.getDisplay(each).toLowerCase() == item.toLowerCase();
                                }).length == 1) {
                                scope.$tableWrapper.find("div.form-clickbox:eq("+index+")").attr("selected","selected");
                                scope.selected[index] = true;
                                selectedArr.push(each);
                            } else {
                                scope.selected[index] = false;
                            }
                            index++;
                        });
                    }

                }else{
                    if(scope.dataSource){
                        angular.forEach(scope.dataSource,function () {
                            scope.selected[index] = false;
                            index++;
                        });

                    }
                }
                return selectedArr;
            };

            //根据输入框内容 和已选数组 重新构造 selectedRow 并返回未匹配的key数组
            AssociateMulti.prototype.keywordSelectedRow = function(selectedArr){
                var me = this,
                    scope = me.scope,
                    missKeyArr = [],
                    inputVal = scope.inputText.val();
                if(inputVal){
                    if(angular.isArray(selectedArr)){
                        angular.forEach(selectedArr,function(each){
                            scope.$selectedRow.push(each);
                        })
                    }
                    var arr = [],
                        keywordArr = inputVal.split(scope.valueSeparator);
                    angular.forEach(keywordArr,function(each){
                        if(_(scope.$selectedRow).filter(function(item){
                                if(me.getDisplay(item).toLowerCase()==each.toLowerCase()){
                                    arr.push(item);
                                    return true;
                                }
                                return false;}).length>0){
                        }else{
                            missKeyArr.push(each);
                        }
                    });

                    scope.$selectedRow = me.dupRemoval(arr);
                }else{
                    scope.$selectedRow = [];
                }
                scope.selectedRow = scope.$selectedRow;
                scope.$parent[me.attrs.selectedRow] = scope.$selectedRow;
                return missKeyArr;
            };

            AssociateMulti.prototype.selectedRowToModelValue = function(val){
                var me = this,
                    scope = me.scope,
                    modelValue;
                var submitArray = [];
                angular.forEach(scope.$selectedRow,function(each){
                    if(scope.valuePropGetter(each)){
                        submitArray.push(scope.valuePropGetter(each));
                    }
                });
                if(val){
                    submitArray.push(val);
                }
                modelValue = submitArray.join(scope.valueSeparator);
                scope.setModelValue(modelValue);
                return modelValue;
            };

            AssociateMulti.prototype.selectedRowToDisplay = function(val){
                var me = this,
                    scope = me.scope,
                    lastChar='';
                var displayArray = [];
                angular.forEach(scope.$selectedRow,function(each){
                    if(me.getDisplay(each)){
                        displayArray.push(me.getDisplay(each));
                    }
                });
                if(val){
                    displayArray.push(val);
                }
                if(scope.inputText.val().charAt(scope.inputText.val().length-1)===scope.valueSeparator){
                    lastChar = scope.valueSeparator;
                }
                scope.inputText.val(displayArray.join(scope.valueSeparator)+lastChar);
                if(me.attrs.keyword){
                    scope.keyword = scope.inputText.val();
                }
            };

            AssociateMulti.prototype.displayInit = function(display,value){
                var myScope = this.scope,
                    displayArr = display.split(myScope.valueSeparator),
                    valueArr = value.split(myScope.valueSeparator),
                    i,
                    length=displayArr.length;
                    for(i=0;i<length;i++){
                        if(!myScope.$selectedRow[i]){
                            myScope.$selectedRow[i] = {};
                        }
                        myScope.$selectedRow[i][myScope.displayExpress] = displayArr[i];
                        myScope.$selectedRow[i][myScope.valueProp] = valueArr[i];
                    }
                myScope.selectedRow = myScope.$selectedRow;
            };

            AssociateMulti.prototype.choseFirst = function(){
                var me = this,
                    scope = me.scope;
                if(scope.dataSource && scope.dataSource.length==1){
                    var rowData = scope.dataSource[0];
                    if(scope.inputText.val().toLowerCase()===me.getDisplay(rowData).toLowerCase()){
                        me.rowClick(scope.dataSource[0]);
                        return true;
                    }else{
                        if(scope.unmatchRemove && scope.isOperSelf){
                            scope.$selectedRow = [];
                            scope.setModelValue('');
                        }
                    }
                }
                return false;
            };

            AssociateMulti.prototype.unmatchKeep = function(){
                var me = this,
                    textValue,
                    textTemp,
                    modelTemp,
                    selectedArr = me.keywordSelected(),
                    missKeyArr = me.keywordSelectedRow(selectedArr),
                    scope = me.scope;
                var modelValue = me.selectedRowToModelValue();
                var displayArray = [];
                angular.forEach(scope.$selectedRow,function(each){
                    displayArray.push(me.getDisplay(each));
                });
                if(missKeyArr.length>0){
                    var missKeyArrTemp = [];
                    //on-before执行
                    angular.forEach(missKeyArr,function(misskey){
                        var obj = {};
                        obj[scope.displayExpress] = misskey;
                        obj[scope.valueProp] = misskey;
                        if (angular.isDefined(me.attrs.onBeforeSelect)) {
                            if (scope.onBeforeSelect({
                                    list: me,
                                    $event:null,
                                    item: obj
                                }) === false) {

                            }else{
                                missKeyArrTemp.push(misskey);
                            }
                        }else{
                            missKeyArrTemp.push(misskey);
                        }
                    });
                    missKeyArr = missKeyArrTemp;

                    textValue = scope.inputText.val();
                    if(textValue){
                        textTemp = displayArray.join(scope.valueSeparator) ;
                        modelTemp = modelValue;
                        if(textTemp.length>0){
                            textTemp += scope.valueSeparator;
                            modelTemp += scope.valueSeparator;
                        }
                        scope.inputText.val(textTemp + missKeyArr.join(scope.valueSeparator));
                        scope.setModelValue(modelTemp + missKeyArr.join(scope.valueSeparator));
                    }else{
                        scope.inputText.val(missKeyArr.join(scope.valueSeparator));
                        scope.setModelValue(missKeyArr.join(scope.valueSeparator));
                    }
                    angular.forEach(missKeyArr,function(misskey){
                        if (angular.isDefined(me.attrs.onSelect)) {
                            var obj = {};
                            obj[scope.displayExpress] = misskey;
                            obj[scope.valueProp] = misskey;
                            scope.onSelect({
                                list: me,
                                $event:null,
                                item: obj
                            });
                        }
                    });
                }
            };

            return AssociateMulti;
        })(Associate);
        return {
            restrict: 'E',
            template: '<input type="text" autocomplete="off" class="form-text form-suggestbox" value=""  />',
            priority: 100,
            replace:true,
            transclude:true,
            scope: {

                sourceName:'@',
                keywordProp: '@',
                multi:'@',

                ngModelInit:'=ngModel',

                keyword:'=',
                requestStatus:'=',

                displayExpress: '@',
                valueProp:'@',
                selectedRow: '=',
                displayInit:'=',
                onSelect:'&',
                onBeforeSelect:'&'
            },
            require: ['^?ngModel','gAssociate'],
            controller:function($scope, $element, $attrs){
                $tabindex.register($element, $element);
                $scope.columns = $scope.columns || [];
                $scope.filters = $scope.filters || [];
                function myController(){
                    this.addColumn=function(col){
                        $scope.columns.push(col);
                    };
                    this.addFilterName=function(filterName){
                        $scope.filters.push(filterName);
                    }
                }
                return new myController();
            },
            compile:function (tElement, tAttrs,transclude) {
                if(tAttrs.ngModel){

                }
                return function (scope, element, attrs, controllers) {
                    var keywordProperty = scope.keywordProp || scope.displayExpress ||'keyword',
                        totalCountProperty = scope.totalCountProp || 'totalCount',
                        valueProp = scope.valueProp || scope.displayExpress || 'id',
                        myController= controllers[1],
                        ngModel= controllers[0],
                        tempWord ='',
                        stopWatch;
                    scope.valueSeparator = attrs.valueSeparator || ',';

                    scope.multi = attrs.multi == "true";
                    scope.$selectedRow = scope.selectedRow || (scope.multi?[]:{});
                    //scope.emptySearch = attrs.emptySearch=="true" || false;
                    scope.charLengthSearch = attrs.charLengthSearch || 0;
                    scope.focusSearch = attrs.focusSearch == "false"?false:true;
                    scope.spaceClear = attrs.spaceClear == "false"?false:true;
                    scope.pageShow = attrs.pageShow == "false"?false:true;
                    scope.showEvent = attrs.showEvent == "click"?"click":"focus";
                    scope.unmatchRemove = attrs.unmatchRemove=="true" || false;//不匹配的是否自动删除
                    scope.deleteOperate = false;//是否删除操作
                    scope.delayTime = attrs.delayTime || 300;
                    scope.columns = scope.columns || [];
                    scope.filters = scope.filters || [];
                    scope.inputText = element;

                    scope.tableShow = false;
                    scope.isOperSelf = false;//判断是否是自己在操作 用于更改数组时判断是否更新视图
                    scope.firstTime = true;
                    scope.selected = [];
                    // default properties
                    scope.page = 1;
                    scope.pageSize = Number(attrs.pageSize) || 10;
                    // settergi
                    scope.keywordPropertySetter = $parse(keywordProperty).assign;
                    // getter
                    scope.valuePropGetter = function (row){
                        //$parse(valueProp);
                        if(row[valueProp+"_$bak"]){
                            return row[valueProp+"_$bak"];
                        }else{
                            return row[valueProp];
                        }
                    }

                    element.wrap('<span></span>');

                    scope.associate =
                        scope.multi? new AssociateMulti(scope, element, attrs,ngModel):new Associate(scope, element, attrs,ngModel);
                    var associate = scope.associate;
                        scope.rowClick = function(val,$event,index){
                        associate.rowClick(val,$event,index);
                        if(!scope.multi && !scope.enterClick){
                            //scope.inputText.blur();
                            if(scope.inputText[0] != document.activeElement){
                                if(scope.showEvent == "focus"){
                                    scope.needFocus = true;
                                }
                                scope.inputText.focus();
                            }
                        }else{
                            scope.enterClick = false;
                        }
                    }

                    if(ngModel){
                        ngModel.$formatters.push(function(value){
                            //清空的时候
                            if(!value){
                                if(scope.selectedRow){
                                    scope.selectedRow[scope.displayExpress] = "";
                                    scope.selectedRow[scope.valueProp] = "";
                                }
                                scope.inputText.val('');
                            }
                            ngModel.$setViewValue(value);
                            return value;
                        });
                    }

                    scope.setModelValue = function(val){
                        if(ngModel) {
                            ngModel.$setViewValue(val);
                        }
                    };

                    if(attrs.displayInit){
                        scope.initTime = 0;//只执行一次
                        if(scope.initTime==0&& scope.displayInit && scope.ngModelInit){
                            associate.displayInit(scope.displayInit,scope.ngModelInit);
                            scope.initTime +=1;
                        }
                        //异步加载的时候 执行
                        stopWatch = scope.$watch("displayInit",function(){
                            if(scope.displayInit && scope.ngModelInit){
                                if(!scope.isOperSelf){
                                    //加个操作判断 防止出现中文输入时候 执行这里
                                    associate.displayInit(scope.displayInit,scope.ngModelInit);
                                }
                                //scope.initTime +=1;
                                //stopWatch();
                            }
                        })
                    }
                    //$compile(element)(scope);
                    scope.$tableWrapper = $compile(associateTmpl)(scope);
                    scope.$tableWrapper = GillionLocationService.createHtmltoTop(scope.$tableWrapper);
                    scope.$tableWrapper.on("click",function(){
                        if(scope.unmatchRemove && scope.inputText.val()==''){

                            scope.inputText.val(scope.blurText);
                            if(attrs.keyword){
                                scope.keywordSetter(scope.$parent,scope.blurText);
                            }
                        }
                        if(scope.timer){
                            $timeout.cancel(scope.timer);
                        }
                    })

                    if(attrs.pagerWidth){
                        scope.$tableWrapper.find(".form-suggestbox-pager").css("width",attrs.pagerWidth);
                    }

                    //设置表格的宽度不小于分页栏的宽度
                    scope.$tableWrapper.find("table").css("min-width",scope.$tableWrapper.find(".form-suggestbox-pager").width());

                    //element.after(scope.$tableWrapper);
                    angular.element(window).on("mousewheel",function(){
                        if(scope.tableShow){
                            scope.inputText[0].blur();
                        }
                    });

                    transclude(scope, function (clone) {
                        angular.forEach(clone,function(item){
                            if (item.tagName === 'TH') {
                                var itemHtml = scope.$tableWrapper.find(".transclude-tr").append(item);
                                myController.addColumn(item.getAttribute("display-express") || '');
                                myController.addFilterName(item.getAttribute("filter-name")|| '');
                            }
                        });
                    },myController);

                    if(attrs.multi){
                        scope.$tableWrapper.find("table tr:first-child").prepend( '<th></th>');
                    }

                    //双向绑定
                    if (angular.isString(attrs.selectedRow)) {
                        if(scope.multi){
                            scope.$watch("$selectedRow",function(val){
                                scope.selectedRow = scope.$selectedRow;
                            });
                            scope.$watchCollection("selectedRow",function(val){
                                scope.$selectedRow = val;
                                if(!scope.isOperSelf){
                                    associate.keywordSelected();
                                    associate.selectedRowToModelValue();
                                    associate.selectedRowToDisplay();
                                }
                            });
                        }else{
                            scope.$watch("$selectedRow",function(val){
                                scope.selectedRow = val;
                            }) ;
                            scope.$watch('selectedRow',function(val){
                                scope.$selectedRow = val;
                                if(!scope.isOperSelf){
                                    associate.keywordSelected();
                                    associate.selectedRowToModelValue();
                                    associate.selectedRowToDisplay();
                                }else{
                                    associate.selectedRowToModelValue();
                                }
                            })
                        }
                    }
                    if (attrs.width) {
                        scope.inputText.css("width", attrs.width);
                    }

                    //初显示回选值
                    if(attrs.selectedRow &&  !isEmptyObject(scope.$selectedRow) ){
                        associate.keywordSelected();
                        associate.selectedRowToModelValue();
                        associate.selectedRowToDisplay();
                    }

                    scope.inputText.on("blur", function (event) {
                        if(scope.unmatchRemove){
                            scope.blurText = scope.inputText.val();
                            scope.deleteOperate=true;//离开同删除操作 最后一个得判断
                            associate.showSelected();
                            associate.selectedRowToModelValue();
                            associate.selectedRowToDisplay();
                        }else{
                            if(!associate.choseFirst()){
                                associate.unmatchKeep();
                            }
                        }
                        scope.isOperSelf = false;
                        associate.apply();
                        scope.timer = $timeout(function () {
                            associate.hideView();
                            associate.apply();
                        }, 200);
                    });

                    $document.on('mousedown', function (event) {
                        if (scope.timer) {
                            $timeout.cancel(scope.timer);
                            if(element[0].offsetWidth == 0){
                                scope.$tableWrapper.css("display","none");
                            }
                        }
                        if ( (scope.tableShow||scope.isOperSelf) && element[0] != (event.srcElement || event.target)
                                && scope.$tableWrapper.find(event.srcElement || event.target).length === 0) {

                            if(scope.unmatchRemove){
                                scope.deleteOperate=true;//离开同删除操作 最后一个得判断
                                associate.showSelected();
                                associate.selectedRowToModelValue();
                                associate.selectedRowToDisplay();
                            }else{
                                if(!associate.choseFirst()){
                                    associate.unmatchKeep();
                                }
                            }
                            scope.isOperSelf = false;
                            associate.hideView();
                            associate.apply();
                        }
                    });



                    scope.inputText.on(scope.showEvent, function (event) {
                        if(GillionMsgService.isUnderMasked(scope.inputText[0])){
                            return ;
                        }
                        if(!scope.focusSearch){
                            return;
                        }
                        if(scope.needFocus){
                            scope.needFocus = false;
                            return;
                        }
                        scope.isOperSelf = true;
                        tempWord = scope.inputText.val();
                        if(attrs.keyword){
                            scope.keywordSetter(scope.$parent,tempWord);
                        }
                        scope.firstTime = false;
                        associate.reSearch(1);
                        associate.apply();
                    });

                    if(attrs.keyword){
                        scope.keywordSetter = $parse(attrs.keyword).assign;
                    }
                    if(attrs.requestStatus){
                        scope.requestStatusSetter = $parse(attrs.requestStatus).assign;
                    }
                    scope.currIndex =  scope.currIndex || -1;
                    associate.initDataSource();
                    scope.inputText.on("keydown",function(event){
                        var e = e || event,
                            currKey = e.keyCode || e.which || e.charCode,
                            trs = scope.$tableWrapper.find("tbody tr[ng-click]"),
                            keyLength = trs.length+1;

                        if(currKey==13){
                            if(scope.tableShow){
                                scope.enterClick = true;
                                if(scope.currIndex>-1){
                                    trs[scope.currIndex].click();
                                }else{
                                    trs[0].click();
                                }
                                scope.tableShow = false;
                                associate.apply();
                            }
                            event.stopPropagation();
                            event.preventDefault();
                        }else if(currKey==37 || currKey==39){
                            event.stopPropagation();
                            event.preventDefault();
                        }
                    });

                    scope.$on("showView",function(){
                        if(scope.tableShow == true){
                            $timeout(function(){
                                associate.showView();
                            });

                        }
                    })

                    scope.inputText.on('keyup', function (event) {
                        var e = e || event,
                            currKey = e.keyCode || e.which || e.charCode,
                            trs = scope.$tableWrapper.find("tbody tr[ng-click]"),
                            keyLength = trs.length+1;
                        scope.isOperSelf = true;

                        if( scope.unmatchRemove){
                            scope.tempNgModel = '';
                        }

                        switch (currKey) {
                            //方向左键
                            case 37:
                                if (1 < scope.page) {
                                    scope.$apply(function(){
                                        associate.goPage(scope.page - 1);
                                    })
                                }
                                event.stopPropagation();
                                event.preventDefault();
                                break;
                            //方向右键
                            case 39:
                                if(scope.page + 1 <= scope.totalPage){
                                    var tempPage =  scope.page + 1;
                                    scope.$apply(function(){
                                        associate.goPage(tempPage);
                                    })
                                }
                                event.stopPropagation();
                                event.preventDefault();
                                break;
                            //方向上键
                            case 38:
                                trs.removeClass("current");
                                scope.currIndex = (scope.currIndex+keyLength-1)%keyLength;
                                trs.eq([scope.currIndex]).addClass("current");
                                event.stopPropagation();
                                event.preventDefault();
                                break;
                            //方向下键
                            case 40:
                                trs.removeClass("current");
                                scope.currIndex = (scope.currIndex+keyLength+1)%keyLength;
                                trs.eq([scope.currIndex]).addClass("current");
                                event.stopPropagation();
                                event.preventDefault();
                                break;
                            //空格键
                            case 32:
                                var inputTextVal = scope.inputText.val();
                                if(inputTextVal.length > 0 && scope.spaceClear){
                                    if(inputTextVal.charAt(0) == ' '|| inputTextVal.charAt(inputTextVal.length-1) == ' '){
                                        scope.inputText.val(scope.inputText.val().replace(/(^\s*)|(\s*$)/g,""));
                                    }
                                }
                                if(trs[scope.currIndex]){
                                    trs[scope.currIndex].click();
                                }else{
                                    tempWord = scope.inputText.val();
                                    if(attrs.keyword){
                                        //因为延迟 所以在这里直接赋值父scope的keyword属性
                                        scope.keywordSetter(scope.$parent,tempWord);
                                    }
                                    associate.reSearch(scope.delayTime);
                                }
                                return false;
                                break;
                            //回车键
                            case 13:
                                //TODO

                                break;
                            default :
                                currKey==8?scope.deleteOperate=true:scope.deleteOperate=false;
                                if(scope.deleteOperate && scope.inputText.val() == ""){
                                    if(scope.multi){
                                        scope.selectedRow = [];
                                        scope.$parent[attrs.selectedRow] = [];
                                    }else{
                                        scope.$selectedRow[scope.displayExpress] = "";
                                        scope.$selectedRow[scope.valueProp] = "";

                                        if(scope.$selectedRow[scope.valueProp+"_$bak"]){
                                            scope.$selectedRow[scope.valueProp+"_$bak"] = "";
                                        }
                                    }

                                }
                                if(tempWord == scope.inputText.val() && tempWord != ""){
                                    //防止重复提交
                                    associate.showView();
                                    associate.apply();
                                    break;
                                }
                                tempWord = scope.inputText.val();

                                if(scope.selectedRow && !scope.unmatchRemove){
                                    scope.selectedRow[scope.displayExpress] = tempWord;
                                    scope.selectedRow[scope.valueProp] = tempWord;
                                }

                                if(attrs.keyword){
                                    //因为延迟 所以在这里直接赋值父scope的keyword属性
                                    scope.keywordSetter(scope.$parent,tempWord);
                                }
                                associate.reSearch(scope.delayTime);
                                break;
                            return false;
                        }
                    });
                }
            }
        };
    };
});